﻿using Microsoft.Win32;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Forms;

namespace DesktopLauncher
{
    class RegistryManager
    {
        private MenuItemExtended mainMenu;
        private DesignerForm designerForm;
        public RegistryManager()
        { }

        public RegistryManager(DesignerForm designerForm)
        {
            this.designerForm = designerForm;
        }

        public RegistryManager(MenuItemExtended mainMenu)
        {
            this.mainMenu = mainMenu;
        }

        public void DeleteMenuFromRegistry()
        {
            RegistryKey backgroundShell = Registry.ClassesRoot.OpenSubKey(@"Directory\Background\shell", RegistryKeyPermissionCheck.ReadWriteSubTree, System.Security.AccessControl.RegistryRights.FullControl);

            if (backgroundShell.OpenSubKey("DesktopLauncher") != null)
            {
                DeleteSubMenusFromRegistry(backgroundShell.OpenSubKey("DesktopLauncher").GetValue("SubCommands").ToString().Split(';'));
                backgroundShell.DeleteSubKeyTree("DesktopLauncher");
            }
        }

        private void DeleteSubMenusFromRegistry(string[] subCommands)
        {
            foreach (string command in subCommands)
            {
                if (String.IsNullOrEmpty(command)) continue;

                MenuItemExtended menuItem = new MenuItemExtended();
                RegistryKey commandStoreShell = Registry.LocalMachine.OpenSubKey(@"SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\CommandStore\shell", RegistryKeyPermissionCheck.ReadWriteSubTree, System.Security.AccessControl.RegistryRights.FullControl);

                if (commandStoreShell.OpenSubKey(command) == null) continue;

                if (commandStoreShell.OpenSubKey(command).GetValue("SubCommands") != null)
                {
                    string[] itemSubCommands = commandStoreShell.OpenSubKey(command).GetValue("SubCommands").ToString().Split(';');
                    DeleteSubMenusFromRegistry(itemSubCommands);
                }

                commandStoreShell.DeleteSubKeyTree(command);
            }
        }



        public MenuItemExtended LoadMenuFromRegistry()
        {
            MenuItemExtended mainMenu = new MenuItemExtended();
            mainMenu.Text = "..::Desktop Launcher::..";
            mainMenu.MouseUp += designerForm.mainItem_MouseUp;
            RegistryKey backgroundShell = Registry.ClassesRoot.OpenSubKey(@"Directory\Background\shell");

            backgroundShell = backgroundShell.OpenSubKey("DesktopLauncher");
            if (backgroundShell != null)
            {
                mainMenu.Text = backgroundShell.GetValue("MUIVerb") as string;
                mainMenu.ImagePath = backgroundShell.GetValue("Icon") as string;
                mainMenu.Image = InputDialog.GetImageFromPath(mainMenu.ImagePath);
                if (backgroundShell.OpenSubKey("Command") != null)
                    mainMenu.RunPath = backgroundShell.OpenSubKey("Command").GetValue("") as string;

                mainMenu = LoadSubMenusFromRegistry(mainMenu, backgroundShell.GetValue("SubCommands").ToString().Split(';'));
            }

            return mainMenu;
        }

        private MenuItemExtended LoadSubMenusFromRegistry(MenuItemExtended menu, string[] subCommands)
        {
            foreach (string command in subCommands)
            {
                if (String.IsNullOrEmpty(command)) continue;

                MenuItemExtended menuItem = new MenuItemExtended();
                RegistryKey commandStoreShell = Registry.LocalMachine.OpenSubKey(@"SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\CommandStore\shell");
                commandStoreShell = commandStoreShell.OpenSubKey(command);

                if (commandStoreShell == null) continue;

                menuItem.Parrent = menu;
                menuItem.Text = commandStoreShell.GetValue("MUIVerb") as string;
                menuItem.ImagePath = commandStoreShell.GetValue("Icon") as string;
                menuItem.Image = InputDialog.GetImageFromPath(menuItem.ImagePath);
                menuItem.MouseUp += designerForm.mainItem_MouseUp;
                if (commandStoreShell.OpenSubKey("Command") != null)
                    menuItem.RunPath = commandStoreShell.OpenSubKey("Command").GetValue("") as string;

                if (commandStoreShell.GetValue("SubCommands") != null)
                {
                    string[] itemSubCommands = commandStoreShell.GetValue("SubCommands").ToString().Split(';');
                    LoadSubMenusFromRegistry(menuItem, itemSubCommands);
                }

                menu.DropDownItems.Add(menuItem);
            }
            return menu;
        }



        public void RegisterDesktopLauncherItems()
        {
            if (mainMenu == null) throw new Exception("Value of mainMenu is null!");

            RegistryKey backgroundShell = Registry.ClassesRoot.OpenSubKey(@"Directory\Background\shell", RegistryKeyPermissionCheck.ReadWriteSubTree, System.Security.AccessControl.RegistryRights.FullControl);

            backgroundShell = backgroundShell.CreateSubKey("DesktopLauncher", RegistryKeyPermissionCheck.ReadWriteSubTree);
            backgroundShell.SetValue("MUIVerb", mainMenu.Text);
            backgroundShell.SetValue("Position", "top");
            if (!String.IsNullOrEmpty(mainMenu.ImagePath))
                backgroundShell.SetValue("Icon", mainMenu.ImagePath);

            if (mainMenu.HasDropDownItems)
            {
                backgroundShell.SetValue("SubCommands", GetMenuItemsAsCSV(mainMenu));
            }

            if (!String.IsNullOrEmpty(mainMenu.RunPath))
            {
                backgroundShell = backgroundShell.CreateSubKey("Command", RegistryKeyPermissionCheck.ReadWriteSubTree);
                backgroundShell.SetValue("", mainMenu.RunPath);
            }

            backgroundShell.Close();

            RegisterDesktopLauncherSubItems(mainMenu);
        }

        private void RegisterDesktopLauncherSubItems(MenuItemExtended menu)
        {
            foreach (MenuItemExtended item in menu.DropDownItems)
            {
                RegistryKey commandStoreShell = Registry.LocalMachine.OpenSubKey(@"SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\CommandStore\shell", RegistryKeyPermissionCheck.ReadWriteSubTree, System.Security.AccessControl.RegistryRights.FullControl);

                commandStoreShell = commandStoreShell.CreateSubKey(GetParrentText(menu) + item.Text.RemoveInvalidCharacters(), RegistryKeyPermissionCheck.ReadWriteSubTree);
                commandStoreShell.SetValue("MUIVerb", item.Text);
                if (!String.IsNullOrEmpty(item.ImagePath))
                    commandStoreShell.SetValue("Icon", item.ImagePath);

                if (item.HasDropDownItems)
                    commandStoreShell.SetValue("SubCommands", GetMenuItemsAsCSV(item));

                if (!String.IsNullOrEmpty(item.RunPath))
                {
                    commandStoreShell = commandStoreShell.CreateSubKey("Command", RegistryKeyPermissionCheck.ReadWriteSubTree);
                    commandStoreShell.SetValue("", item.RunPath);
                }

                commandStoreShell.Close();

                if (item.HasDropDownItems)
                    RegisterDesktopLauncherSubItems(item);
            }
        }

        /// <summary>
        /// Menu1 -> this MenuItem as a parameter
        ///     - SubMenu1
        ///         - SubSubMenu1
        ///     - SubMenu2
        /// Menu2
        /// 
        /// Will return "Menu1.SubMenu1;Menu1.SubMenu2;"
        /// </summary>
        /// <param name="menu"></param>
        /// <returns></returns>
        private string GetMenuItemsAsCSV(MenuItemExtended menu)
        {
            string prefix = GetParrentText(menu);
            string menuItems = "";

            foreach (MenuItemExtended item in menu.DropDownItems)
                menuItems += prefix + item.Text.RemoveInvalidCharacters() + ";";

            return menuItems;
        }

        /// <summary>
        /// ..::MyLauncher::..
        /// Menu1
        ///     - SubMenu1
        ///         - SubSubMenu1 -> this MenuItem is a parameter
        ///     - SubMenu2
        /// Menu2
        /// 
        /// Will return "DesktopLauncher.Menu1.SubMenu1.SubSubMenu1." using recursion
        /// First will be always "DesktopLauncher" cause of registry order
        /// </summary>
        /// <param name="menu"></param>
        /// <returns></returns>
        private string GetParrentText(MenuItemExtended menu)
        {
            string prefix = "";
            if (menu.Parrent != null)
                prefix += GetParrentText(menu.Parrent);

            if (menu.Parrent == null)
                prefix = "DesktopLauncher." + prefix;
            else
                prefix += menu.Text.RemoveInvalidCharacters() + ".";

            return prefix;
        }
    }
}
